﻿//++
//
// Copyright (c) Microsoft Corporation.  All rights reserved.
//
// Module Name:
//
//  AddChannelWindow.cs
//    
// Abstract:
//
//  Code-beside for the Add/Edit Channel Dialog
//  
//--

using System.ComponentModel;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;

namespace Microsoft.EnhancedReminders.OutlookAddIn
{
    /// <summary>
    /// Represents a NotificationChannelType displayed as an option in the Add/Edit
    /// Channel Dialog.
    /// </summary>
    public class ChannelItem
    {
        private NotificationChannelType _channelType;
        private string _displayName;
        private string _addressIdentifier;
        private string _exampleText;
        private string _imageUri;

        /// <summary>
        /// ctor.
        /// </summary>
        /// <param name="type">The type of channel</param>
        /// <param name="displayName">The localized name to display for this channel</param>
        /// <param name="address">The text to display for the "address" (e.g., "Phone Number")</param>
        /// <param name="example">An example string to display how to format the channel addres</param>
        /// <param name="image">An image representing the channel</param>
        public ChannelItem(NotificationChannelType type, string displayName, string address, string example, string image)
        {
            Debug.Assert(!string.IsNullOrEmpty(displayName), "!string.IsNullOrEmpty(displayName)");
            Debug.Assert(!string.IsNullOrEmpty(address), "!string.IsNullOrEmpty(address)");
            Debug.Assert(!string.IsNullOrEmpty(example), "!string.IsNullOrEmpty(example)");
            Debug.Assert(!string.IsNullOrEmpty(image), "!string.IsNullOrEmpty(image)");

            _channelType = type;
            _displayName = displayName;
            _addressIdentifier = address;
            _exampleText = example;
            _imageUri = image;
        }

        /// <summary>
        /// The channel type
        /// </summary>
        public NotificationChannelType ChannelType
        {
            get
            {
                return _channelType;
            }
            set
            {
                _channelType = value;
            }
        }

        /// <summary>
        /// The name to display for this channel type
        /// </summary>
        public string DisplayName
        {
            get
            {
                return _displayName;
            }
            set
            {
                _displayName = value;
            }
        }

        /// <summary>
        /// The URI for the image to display in the Combo Box
        /// </summary>
        public string ImageSource
        {
            get
            {
                return _imageUri;
            }
            set
            {
                _imageUri = value;
            }
        }

        /// <summary>
        /// An example of the expected format of the channel address
        /// </summary>
        public string ExampleText
        {
            get
            {
                return _exampleText;
            }
        }

        /// <summary>
        /// The name of the 'address.' For example "Phone Number" for the phone channel.
        /// </summary>
        public string AddressIdentifier
        {
            get
            {
                return _addressIdentifier;
            }
            set
            {
                _addressIdentifier = value;
            }
        }
    }

    /// <summary>
    /// Represents a modal dialog used for adding new or editing existing Notification
    /// Channels to a Reminder Item.
    /// </summary>
   public partial class AddEditChannelDialog : INotifyPropertyChanged
   {
        // regular expression string for matching an e-mail address. This
        // was taken from MSDN (http://msdn2.microsoft.com/en-us/library/01escwtf(VS.71).aspx),
        private const string emailRegularExpression = @"^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
        
        // regular expression string for matching characters that may appear in a phone number;
        // this is any digit, periods, parenthesis, plusses, dashes, and spaces.
        private const string phoneNumberRegularExpression = @"^[0-9\.\(\)\+\-\s]+$";

        /// <summary>
        /// ctor.
        /// </summary>
        /// <param name="channel">A NotificationChannel to edit, or null if a new one is to be added.</param>
        /// <remarks>Note that this method may change the channel passed in even if cancel is hit, so
        /// callers are expected to make a copy of any NotificationChannels they wish to edit.</remarks>
        public AddEditChannelDialog(NotificationChannel channel)     
        {
            this.InitializeComponent();
         
            if (channel == null) // Add a new custom (non-OCS) channel.
            {
                Title = Microsoft.EnhancedReminders.Properties.Resources.AddChannelDialogTitle;
                DataContext = new NotificationCustomChannel();
            }
            else // Edit an existing OCS or custom channel.
            {
                Title = Microsoft.EnhancedReminders.Properties.Resources.EditChannelDialogTitle;
                DataContext = channel;
                isTopOfList.IsChecked = false;

                if (channel.GetType() == typeof(NotificationChannel)) // Disallow editing of OCS channel type and name fields.
                {
                    selectChannel.IsEnabled = false;
                    nameText.IsEnabled = false;
                    
                    if (channel.Id == NotificationChannel.CommunicatorId ||
                        channel.Id == NotificationChannel.WorkPhoneId)
                    {
                        addressText.IsEnabled = false; // OCS work phone and communicator channels are read only.
                    }
                }
            }
 
            selectChannel.ItemsSource = new ChannelItem[] {
                new ChannelItem(NotificationChannelType.Communicator, Microsoft.EnhancedReminders.Properties.Resources.Communicator, Microsoft.EnhancedReminders.Properties.Resources.Communicator_Address, Microsoft.EnhancedReminders.Properties.Resources.Communicator_Example, @"..\Images\im-small.png"),
                new ChannelItem(NotificationChannelType.Phone, Microsoft.EnhancedReminders.Properties.Resources.Phone, Microsoft.EnhancedReminders.Properties.Resources.Phone_Address, Microsoft.EnhancedReminders.Properties.Resources.Phone_Example, @"..\Images\phone-small.png"),
                new ChannelItem(NotificationChannelType.SMS, Microsoft.EnhancedReminders.Properties.Resources.SMS, Microsoft.EnhancedReminders.Properties.Resources.SMS_Address, Microsoft.EnhancedReminders.Properties.Resources.SMS_Example, @"..\Images\sms-small.png")
            };

            // Override the default background color so it matches that of the buttons.
            Background = okButton.Background;

            addressText.TextChanged += addressText_TextChanged;
            nameText.TextChanged += addressText_TextChanged;
            selectChannel.SelectionChanged += selectChannel_SelectionChanged;
      }

        private void selectChannel_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            OnPropertyChanged("IsChannelValid");
        }

        private void addressText_TextChanged(object sender, TextChangedEventArgs e)
        {
            OnPropertyChanged("IsChannelValid");
        }

        private void isEnabled_Clicked(object sender, RoutedEventArgs e)
        {
            OnPropertyChanged("IsChannelValid");
        }

        /// <summary>
        /// Returns the Notification Channel that this dialog is editing.
        /// </summary>
        public NotificationChannel Channel
        {
            get
            {
                return DataContext as NotificationChannel;               
            }
        }

        /// <summary>
        /// Returns whether or not the Notification Channel should be added
        /// to the top of the list.
        /// </summary>
        public bool AddToTop
        {
            get
            {
                return isTopOfList.IsChecked.Value;
            }
        }

        /// <summary>
        /// Event handler for when the OK button is clicked.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OkButtonClicked(object sender, RoutedEventArgs e)
        {
            DialogResult = true;
        }

        /// <summary>
        /// Returns whether or not the current channel is valid, which we use to determine
        /// whether or not the "OK" button should be enabled.
        /// </summary>
        public bool IsChannelValid
        {
            get
            {
                if (Channel == null || 
                    string.IsNullOrEmpty(Channel.UserDefinedName) || 
                    (string.IsNullOrEmpty(Channel.UserDefinedValue) && (Channel is NotificationCustomChannel || Channel.IsEnabled)))
                {
                    return false;
                }
                else if (Channel.GetType() == typeof(NotificationChannel) && 
                         string.IsNullOrEmpty(Channel.UserDefinedValue))
                {
                    return true; // OCS channels can have an empty value (but only if !IsEnabled).
                }
                else if (Channel.NotificationChannelType == NotificationChannelType.SMS ||
                         Channel.NotificationChannelType == NotificationChannelType.Communicator)
                {
                    Regex regex = new Regex(emailRegularExpression);

                    return regex.IsMatch(Channel.UserDefinedValue);
                }
                else if (Channel.NotificationChannelType == NotificationChannelType.Phone)
                {
                    Regex regex = new Regex(phoneNumberRegularExpression);

                    return regex.IsMatch(Channel.UserDefinedValue);
                }

                return true;
            }
        }

        private void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler callback = PropertyChanged;

            if (callback != null)
            {
                callback(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Event to be raised when a property changes.
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}